package rendava;
import java.awt.FontMetrics;
import java.awt.Graphics;
import javax.swing.JPanel;
import javax.swing.JFrame;
/**
 * Renderer class. For rendering.
 * 
 * @author Ben Gomm & Farrell Hayman
 * @version 0.5
 *
 */

public class Renderer {
	
	private float zoomLevel = 1;
	private int xCord = 1;
	private int yCord = 20;
	private Tag state;
	private JPanel canvas;
	private GUI gui;
	private Graphics graphics;
	public Tree tree;
	private boolean returning = false;
	private boolean bold;
	private boolean italic;
	private boolean blockquote;
	private boolean paragraph;
	private boolean unorderedList = false;
	private boolean orderedList = false;
	private boolean definitionList = false;
	private boolean table;
	private boolean centre;
	private int listNumber = 0;
	public boolean title = false;

	
	public Renderer(Tree t, JPanel c, GUI gui)
	{
		this.gui = gui;
		canvas = c;
		tree = t;
		graphics = canvas.getGraphics();
		renderDocument(tree, canvas);
		JFrame frame = new JFrame();
		frame.setDefaultCloseOperation(frame.EXIT_ON_CLOSE);
		frame.getContentPane().add(canvas);
	}
	
	/**
	 * Returns the zoom level currently set.
	 * 
	 * @return zoom level.
	 */
	public float getZoomLevel()
	{
		return zoomLevel;
	}
	/**
	 * Sets the zoom level.
	 * 
	 * @param modifier amount to multiply the zoom level by.
	 */
	public void setZoomLevel(float modifier)
	{
		zoomLevel = zoomLevel * modifier;
	}
	
	/**
	 * Giant method that does everything to do with rendering
	 * @param t The tree to render.
	 * @param c The canvas which has the graphics we'll be manipulating
	 */
	public void renderDocument(Tree t, JPanel c)
	{
		
		state = getNextTag();
		while (state != null)
		{
			if (state.closeTag().equals("</ol>") && returning == false)
			{
				orderedList = false;
			}
			if(state.closeTag().equals("</li>") && returning == false)
			{
				FontMetrics fm = graphics.getFontMetrics();
				int newY = getY() + fm.getHeight();
				setY(newY);//sets Y on a new Line
				setX(2);//Sets X to start from the beginning
				if(orderedList)
				{
					listNumber++;
					System.out.println("listnumber is "+ listNumber);
					setX(30);
					graphics.drawString(listNumber + ". ", xCord, yCord);
					state.renderInfo(this);
					if(tree.getChildTag(state) == null) // if the current element has a child and we aren't returning from it
					{
						state = tree.getParentTag(state); 
						state = tree.getSiblingTag(state);// do something..(if there are nested lists then how do we keep track?)
					}
					else if (tree.getSiblingTag(state) == null) // if there isnt a sibling tag i.e if the listItems are done
					{
						listNumber = 0;// then reset the list number tracker to 0
						orderedList = false;// makes the orderedList false so that it can differentiate between different types of list
					}
				}
				
				else if(unorderedList)
				{
					graphics.drawString(". ", xCord, yCord);
					state.renderInfo(this);
					if (tree.getSiblingTag(state) == null) // if there isnt a sibling tag i.e if the listItems are done
					{
						unorderedList = false;// makes the unorderedList false so that it can differentiate between different types of list
					}
				}
			}
		
	
			if (state.closeTag().equals("</h1>")) // this is too late!
			{
				FontMetrics fm = graphics.getFontMetrics();
				graphics.drawString("1."+listNumber, xCord, yCord);
				setY(getY() + fm.getHeight());
				listNumber++; // needs to be fixed to work with subheaders
			}
			/*
			 * <blockquote>
			 */
			if (state.closeTag().equals("</blockquote>") && returning)
			{
				setX(getX()-10); // undoes blockquote upon close
			}
			/*
			 * This is a check to set the title of the window according to the page. Done in display font.
			 */
			if (state.closeTag().equals("</title>") &&  returning == false) 
			{
				title = true;
			}
			else if (state.closeTag().equals("</title>") && returning)
			{
				title = false;
			}
			/*
			 * All other tags.
			 */
			else
			{
				state.renderInfo(this); // calls the renderer info of each Tag it comes across
			}
		
		 //MUST BE AT THE END OF THE WHILE LOOP:
			state = getNextTag();
			if (state == tree.getRootElement() && returning == true)
			{
				break;
			}
		}
	}
	/**
	 * Traverses the tree and gets the tag we need next. Magically.
	 * @return The next tag we need. Read the comments for more info.
	 */
	public Tag getNextTag()
	{
		if (state == null) // if we have no tag yet
		{
			return tree.getRootElement(); //get the root element in the tree
		}
		else //otherwise
		{
			if(tree.getChildTag(state) != null && returning == false) // if the current element has a child and we aren't returning from it
			{
				return tree.getChildTag(state); //return it
			}
			else if (tree.getSiblingTag(state) != null) // otherwise if there's a sibling tag
			{
				returning = false;
				return tree.getSiblingTag(state); // return it
			}
			else if (tree.getParentTag(state) == null) //otherwise if we're at the top of the tree
			{
				return null; // return nothing
			}
			else //otherwise return the parent
			{
				returning = true; //set returning to true. this means we've got nowhere to go.
				return tree.getParentTag(state);
			}
		}
	}
	
	public JPanel getCanvas()
	{
		return canvas;
	}
	
	public Graphics getGraphics()
	{
		return graphics;
	}
	
	public void setX(int x)
	{
		xCord = x;
	}
	
	public void setY(int y)
	{
		yCord = y;
	}
	
	public int getX()
	{
		return xCord;
	}
	
	public int getY()
	{
		return yCord;
	}
	/**
	 * Returns the current width of the JPanel for calculating rendering.
	 * @return width of canvas(JPanel)
	 */
	public int getCanvasWidth()
	{
		return canvas.getWidth();
	}

	
	public void incListNumber()
	{
		listNumber++;
	}
	
	public int getListNumber()
	{
		return listNumber;
	}
	
	public GUI getGUI()
	{
		return gui;
	}
	
	public void increaseListNumber()
	{
		listNumber++;
	}
	/**
	 * Boolean setters for all the boolean fields
	 * @param bool
	 */
	//I dont think we need all the boolean fields. We only need list and table i guess.
	public void setBold(boolean bool)
	{
		bold = bool;
	}
	
	public void setItalic(boolean bool)
	{
		italic = bool;
	}
	
	public void setBlockQuote(boolean bool)
	{
		blockquote = bool;
	}
	
	public void setParagraph(boolean bool)
	{
		paragraph = bool;
	}
	
	public void setUnorderedList(boolean bool)
	{
		unorderedList = bool;
	}
	
	public void setOrderedList(boolean bool)
	{
		orderedList = bool;
	}
	
	public void setDefinitionList(boolean bool)
	{
		definitionList = bool;
	}
	
	public void setTable(boolean bool)
	{
		table = bool;
	}

	public void setCenter(boolean bool)
	{
		centre = bool;
	}
	
}
